package ezXpns.storage.queries;

import java.util.Locale;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.DateTools.Resolution;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.index.Term;

import ezXpns.storage.LuceneConfig;
import ezXpns.storage.Query;


//@author A0088827L
public class RawLuceneQuery<T> implements Query<T> {
	public RawLuceneQuery(String qs) throws ParseException {
		QueryParser queryParser = new Parser();
		luceneQuery = queryParser.parse(qs);
	}

	@Override
	public boolean apply(T arg) {
		return true;
	}

	@Override
	public org.apache.lucene.search.Query asLuceneQuery() {
		return luceneQuery;
	}

	private org.apache.lucene.search.Query luceneQuery;
	
	private class Parser extends QueryParser {
		public Parser() {
			super(LuceneConfig.LUCENE_VERSION, "name", LuceneConfig.ANALYZER);
			setDefaultOperator(Operator.AND);
			setDateResolution("date", Resolution.MILLISECOND);
			setLocale(Locale.getDefault());
			setAnalyzeRangeTerms(true);
		}
		
		@Override
		protected org.apache.lucene.search.Query newFieldQuery(
				Analyzer analyzer,
                String field,
                String queryText,
                boolean quoted) {
			return new TermQuery(new Term(field, queryText));
		}

		@Override
		protected org.apache.lucene.search.Query newRangeQuery(
				String field,
                String left,
                String right,
                boolean startInclusive,
                boolean endInclusive) {
			
			switch(field) {
			case "amount":
			case "price":
				return NumericRangeQuery.newFloatRange(
					"amount",
					Float.parseFloat(left),
					Float.parseFloat(right),
					startInclusive,
					endInclusive
				);
			case "date":
				long minDate, maxDate;
				try {
					minDate = DateTools.stringToTime(left);
					maxDate = DateTools.stringToTime(right);
				} catch (java.text.ParseException e) {
					e.printStackTrace();
					return null;
				}
				return NumericRangeQuery.newLongRange(
					"date",
					minDate,
					maxDate,
					startInclusive,
					endInclusive
				);
			default:
				return super.newRangeQuery(field, left, right, startInclusive, endInclusive);
			}
		}
	}
}
